# 除了ARM和X86定义以外其他的处理器结构未定义
from ctypes import *
from enum import *
from kvm_x86_types import *

from ioctl_opt import IO, IOW, IOR

# kvm版本信息
KVM_API_VERSION = 12

KVM_TRC_SHIFT = 16
KVM_TRC_ENTRYEXIT = 1 << KVM_TRC_SHIFT
KVM_TRC_HANDLER = 1 << (KVM_TRC_SHIFT + 1)
KVM_TRC_VMENTRY = KVM_TRC_ENTRYEXIT + 0x01
KVM_TRC_VMEXIT = KVM_TRC_ENTRYEXIT + 0x02
KVM_TRC_PAGE_FAULT = KVM_TRC_HANDLER + 0x01
KVM_TRC_HEAD_SIZE = 12
KVM_TRC_CYCLE_SIZE = 8
KVM_TRC_EXTRA_MAX = 7

KVM_TRC_INJ_VIRQ = (KVM_TRC_HANDLER + 0x02)
KVM_TRC_REDELIVER_EVT = (KVM_TRC_HANDLER + 0x03)
KVM_TRC_PEND_INTR = (KVM_TRC_HANDLER + 0x04)
KVM_TRC_IO_READ = (KVM_TRC_HANDLER + 0x05)
KVM_TRC_IO_WRITE = (KVM_TRC_HANDLER + 0x06)
KVM_TRC_CR_READ = (KVM_TRC_HANDLER + 0x07)
KVM_TRC_CR_WRITE = (KVM_TRC_HANDLER + 0x08)
KVM_TRC_DR_READ = (KVM_TRC_HANDLER + 0x09)
KVM_TRC_DR_WRITE = (KVM_TRC_HANDLER + 0x0A)
KVM_TRC_MSR_READ = (KVM_TRC_HANDLER + 0x0B)
KVM_TRC_MSR_WRITE = (KVM_TRC_HANDLER + 0x0C)
KVM_TRC_CPUID = (KVM_TRC_HANDLER + 0x0D)
KVM_TRC_INTR = (KVM_TRC_HANDLER + 0x0E)
KVM_TRC_NMI = (KVM_TRC_HANDLER + 0x0F)
KVM_TRC_VMMCALL = (KVM_TRC_HANDLER + 0x10)
KVM_TRC_HLT = (KVM_TRC_HANDLER + 0x11)
KVM_TRC_CLTS = (KVM_TRC_HANDLER + 0x12)
KVM_TRC_LMSW = (KVM_TRC_HANDLER + 0x13)
KVM_TRC_APIC_ACCESS = (KVM_TRC_HANDLER + 0x14)
KVM_TRC_TDP_FAULT = (KVM_TRC_HANDLER + 0x15)
KVM_TRC_GTLB_WRITE = (KVM_TRC_HANDLER + 0x16)
KVM_TRC_STLB_WRITE = (KVM_TRC_HANDLER + 0x17)
KVM_TRC_STLB_INVAL = (KVM_TRC_HANDLER + 0x18)
KVM_TRC_PPC_INSTR = (KVM_TRC_HANDLER + 0x19)


class kvm_user_trace_setup(Structure):
    _fields_ = [
        ('buf_size', c_uint32),
        ('buf_nr', c_uint32),
    ]


class kvm_assigned_irq(Structure):
    _fields_ = [
        ('assigned_dev_id', c_uint32),
        ('host_irq', c_uint32),
        ('guest_irq', c_uint32),
        ('flags', c_uint32),
        ('reserved', c_uint32 * 12)
    ]


class kvm_breakpoint(Structure):
    _fields_ = [
        ('enabled', c_uint32),
        ('padding', c_uint32),
        ('address', c_uint64),
    ]


class kvm_debug_guest(Structure):
    _fields_ = [
        ('enabled', c_uint32),
        ('pad', c_uint32),
        ('breakpoints', kvm_breakpoint[4]),
        ('singlestep', c_uint32),
    ]


KVMIO = 0xAE

__KVM_DEPRECATED_MAIN_W_0x06 = IOW(KVMIO, 0x06, kvm_user_trace_setup)
__KVM_DEPRECATED_MAIN_0x07 = IO(KVMIO, 0x07)
__KVM_DEPRECATED_MAIN_0x08 = IO(KVMIO, 0x08)
__KVM_DEPRECATED_VM_R_0x70 = IOR(KVMIO, 0x70, kvm_assigned_irq)
__KVM_DEPRECATED_VCPU_W_0x87 = IOW(KVMIO, 0x87, kvm_debug_guest)


# 用于 KVM_CREATE_MEMORY_REGION
class kvm_memory_region(Structure):
    _fields_ = [
        ('slot', c_uint32),
        ('flags', c_uint32),
        ('guest_phys_addr', c_uint64),
        ('memory_size', c_uint64),  # 单位字节
    ]


# 用于 KVM_SET_USER_MEMORY_REGION
class kvm_userspace_memory_region(Structure):
    _fields_ = [
        ('slot', c_uint32),
        ('flags', c_uint32),
        ('guest_phys_addr', c_uint64),
        ('memory_size', c_uint64),  # 单位字节
        ('userspace_addr', c_uint64),  # 用户态分配的首地址
    ]


class kvm_irq_level_union(Union):
    _fields_ = [
        ('irq', c_uint32),
        ('status', c_int32),
    ]


KVM_MEM_LOG_DIRTY_PAGES = (1 << 0)
KVM_MEM_READONLY = (1 << 1)


class kvm_irq_level(Structure):
    _fields_ = [
        ('slot', c_uint32),
        ('level', c_uint32),
    ]


class kvm_pit_config(Structure):
    _anonymous_ = ('chip',)
    _fields_ = [
        ('flags', c_uint32),
        ('pad', c_uint32 * 15),
    ]


# kvm退出原因定义
KVM_EXIT_UNKNOWN = 0
KVM_EXIT_EXCEPTION = 1
KVM_EXIT_IO = 2
KVM_EXIT_HYPERCALL = 3
KVM_EXIT_DEBUG = 4
KVM_EXIT_HLT = 5
KVM_EXIT_MMIO = 6
KVM_EXIT_IRQ_WINDOW_OPEN = 7
KVM_EXIT_SHUTDOWN = 8
KVM_EXIT_FAIL_ENTRY = 9
KVM_EXIT_INTR = 10
KVM_EXIT_SET_TPR = 11
KVM_EXIT_TPR_ACCESS = 12
KVM_EXIT_S390_SIEIC = 13
KVM_EXIT_S390_RESET = 14
KVM_EXIT_DCR = 15
KVM_EXIT_NMI = 16
KVM_EXIT_INTERNAL_ERROR = 17
KVM_EXIT_OSI = 18
KVM_EXIT_PAPR_HCALL = 19
KVM_EXIT_S390_UCONTROL = 20
KVM_EXIT_WATCHDOG = 21
KVM_EXIT_S390_TSCH = 22
KVM_EXIT_EPR = 23
KVM_EXIT_SYSTEM_EVENT = 24
KVM_EXIT_S390_STSI = 25
KVM_EXIT_IOAPIC_EOI = 26
KVM_EXIT_HYPERV = 27
KVM_EXIT_ARM_NISV = 28
KVM_EXIT_X86_RDMSR = 29
KVM_EXIT_X86_WRMSR = 30

# kvm内部错误定义
KVM_INTERNAL_ERROR_EMULATION = 1  # 指令错误
KVM_INTERNAL_ERROR_SIMUL_EX = 2  # 偶发错误
KVM_INTERNAL_ERROR_DELIVERY_EV = 3  # delivery event vm-exit
KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON = 4  # vm-exit 原因

KVM_EXIT_IO_IN = 0
KVM_EXIT_IO_OUT = 1
KVM_SYSTEM_EVENT_SHUTDOWN = 1
KVM_SYSTEM_EVENT_RESET = 2
KVM_SYSTEM_EVENT_CRASH = 3
KVM_MSR_EXIT_REASON_INVAL = (1 << 0)
KVM_MSR_EXIT_REASON_UNKNOWN = (1 << 1)
KVM_MSR_EXIT_REASON_FILTER = (1 << 2)
SYNC_REGS_SIZE_BYTES = 2048


class _kvm_run_uni_hw(Structure):
    _fields_ = [
        ('hardware_exit_reason', c_uint64),
    ]


class _kvm_run_uni_fail_entry(Structure):
    _fields_ = [
        ('hardware_entry_failure_reason', c_uint64),
        ('cpu', c_uint32)
    ]


class _kvm_run_uni_ex(Structure):
    _fields_ = [
        ('exception', c_uint32),
        ('error_code', c_uint32)
    ]


class _kvm_run_uni_io(Structure):
    _fields_ = [
        ('direction', c_uint8),
        ('size', c_uint8),
        ('port', c_uint16),
        ('count', c_uint32),
        ('data_offset', c_uint64),
    ]


class kvm_debug_exit_arch(Structure):
    _fields_ = [
        ('exception', c_uint32),
        ('pad', c_uint32),
        ('pc', c_uint64),
        ('dr6', c_uint64),
        ('dr7', c_uint64),
    ]


class _kvm_run_uni_debug(Structure):
    _fields_ = [
        ('arch', kvm_debug_exit_arch),
    ]


class _kvm_run_uni_mmio(Structure):
    _fields_ = [
        ('phys_addr', c_uint64),
        ('data', c_uint8 * 8),
        ('len', c_uint32),
        ('is_write', c_uint8),
    ]


class _kvm_run_uni_hypercall(Structure):
    _fields_ = [
        ('nr', c_uint64),
        ('args', c_uint64 * 6),
        ('ret', c_uint64),
        ('longmode', c_uint32),
        ('pad', c_uint32),
    ]


class _kvm_run_uni_tpr_access(Structure):
    _fields_ = [
        ('rip', c_uint64),
        ('is_write', c_uint32),
        ('pad', c_uint32),
    ]


class _kvm_run_uni_internal(Structure):
    _fields_ = [
        ('suberror', c_uint32),
        ('ndata', c_uint32),
        ('data', c_uint64 * 16),
    ]


class _kvm_run_uni_osi(Structure):
    _fields_ = [
        ('gprs', c_uint64 * 32),
    ]


class _kvm_run_uni_papr_hcall(Structure):
    _fields_ = [
        ('nr', c_uint64),
        ('ret', c_uint64),
        ('args', c_uint64 * 9),
    ]


class _kvm_run_uni_epr(Structure):
    _fields_ = [
        ('epr', c_uint32),
    ]


class _kvm_run_uni_system_event(Structure):
    _fields_ = [
        ('type', c_uint32),
        ('flags', c_uint64),
    ]


class _kvm_run_uni_eoi(Structure):
    _fields_ = [
        ('vector', c_uint8),
    ]


class _kvm_run_uni_arm_nisv(Structure):
    _fields_ = [
        ('esr_iss', c_uint64),
        ('fault_ipa', c_uint64),
    ]


class _kvm_run_uni_msr(Structure):
    _fields_ = [
        ('error', c_uint8),
        ('pad', c_uint8 * 7),
        ('reason', c_uint32),
        ('index', c_uint32),
        ('data', c_uint64),
    ]


class _kvm_run_uni(Union):
    _fields_ = [
        ('hw', _kvm_run_uni_hw),
        ('fail_entry', _kvm_run_uni_fail_entry),
        ('ex', _kvm_run_uni_ex),
        ('io', _kvm_run_uni_io),
        ('debug', _kvm_run_uni_debug),
        ('mmio', _kvm_run_uni_mmio),
        ('hypercall', _kvm_run_uni_hypercall),
        ('tpr_access', _kvm_run_uni_tpr_access),
        ('s390_reset_flags', c_uint64),
        ('internal', _kvm_run_uni_internal),
        ('osi', _kvm_run_uni_osi),
        ('papr_hcall', _kvm_run_uni_papr_hcall),
        ('erp', _kvm_run_uni_epr),
        ('system_event', _kvm_run_uni_system_event),
        ('eoi', _kvm_run_uni_eoi),
        ('arm_nisv', _kvm_run_uni_arm_nisv),
        ('msr', _kvm_run_uni_msr),
        ('padding', c_char * 256)
    ]


class _kvm_run_s_uni(Union):
    _fields_ = [
        ('regs', kvm_sync_regs),
        ('padding', c_char * SYNC_REGS_SIZE_BYTES),
    ]


class kvm_run(Structure):
    _fields_ = [
        # in
        ('request_interrupt_window', c_uint8),
        ('immediate_exit', c_uint8),
        ('padding1', c_uint8 * 6),
        # out
        ('exit_reason', c_uint32),
        ('ready_for_interrupt_injection', c_uint8),
        ('if_flag', c_uint8),
        ('flags', c_uint16),
        # in out
        ('cr8', c_uint64),
        ('apic_base', c_uint64),
        # 各个功能区的定义
        ('run_nui', _kvm_run_uni),
        ('kvm_valid_regs', c_uint64),
        ('kvm_dirty_regs', c_uint64),
        # 各个寄存器的状态定义
        ('s', _kvm_run_s_uni),
    ]


# 扩展功能查询列表
# extension capability list
KVM_CAP_IRQCHIP = 0
KVM_CAP_HLT = 1
KVM_CAP_MMU_SHADOW_CACHE_CONTROL = 2
KVM_CAP_USER_MEMORY = 3
KVM_CAP_SET_TSS_ADDR = 4
KVM_CAP_VAPIC = 6
KVM_CAP_EXT_CPUID = 7
KVM_CAP_CLOCKSOURCE = 8
KVM_CAP_NR_VCPUS = 9
KVM_CAP_NR_MEMSLOTS = 10
KVM_CAP_PIT = 11
KVM_CAP_NOP_IO_DELAY = 12
KVM_CAP_PV_MMU = 13
KVM_CAP_MP_STATE = 14
KVM_CAP_COALESCED_MMIO = 15
KVM_CAP_SYNC_MMU = 16
KVM_CAP_IOMMU = 18
KVM_CAP_DESTROY_MEMORY_REGION_WORKS = 21
KVM_CAP_USER_NMI = 22
KVM_CAP_SET_GUEST_DEBUG = 23
KVM_CAP_REINJECT_CONTROL = 24
KVM_CAP_IRQ_ROUTING = 25
KVM_CAP_IRQ_INJECT_STATUS = 26
KVM_CAP_ASSIGN_DEV_IRQ = 29
KVM_CAP_JOIN_MEMORY_REGIONS_WORKS = 30
KVM_CAP_MCE = 31
KVM_CAP_IRQFD = 32
KVM_CAP_PIT2 = 33
KVM_CAP_SET_BOOT_CPU_ID = 34
KVM_CAP_PIT_STATE2 = 35
KVM_CAP_IOEVENTFD = 36
KVM_CAP_SET_IDENTITY_MAP_ADDR = 37
KVM_CAP_XEN_HVM = 38
KVM_CAP_ADJUST_CLOCK = 39
KVM_CAP_INTERNAL_ERROR_DATA = 40
KVM_CAP_VCPU_EVENTS = 41
KVM_CAP_S390_PSW = 42
KVM_CAP_PPC_SEGSTATE = 43
KVM_CAP_HYPERV = 44
KVM_CAP_HYPERV_VAPIC = 45
KVM_CAP_HYPERV_SPIN = 46
KVM_CAP_PCI_SEGMENT = 47
KVM_CAP_PPC_PAIRED_SINGLES = 48
KVM_CAP_INTR_SHADOW = 49
KVM_CAP_DEBUGREGS = 50
KVM_CAP_X86_ROBUST_SINGLESTEP = 51
KVM_CAP_PPC_OSI = 52
KVM_CAP_PPC_UNSET_IRQ = 53
KVM_CAP_ENABLE_CAP = 54
KVM_CAP_XSAVE = 55
KVM_CAP_XCRS = 56
KVM_CAP_PPC_GET_PVINFO = 57
KVM_CAP_PPC_IRQ_LEVEL = 58
KVM_CAP_ASYNC_PF = 59
KVM_CAP_TSC_CONTROL = 60
KVM_CAP_GET_TSC_KHZ = 61
KVM_CAP_PPC_BOOKE_SREGS = 62
KVM_CAP_SPAPR_TCE = 63
KVM_CAP_PPC_SMT = 64
KVM_CAP_PPC_RMA = 65
KVM_CAP_MAX_VCPUS = 66
KVM_CAP_PPC_HIOR = 67
KVM_CAP_PPC_PAPR = 68
KVM_CAP_SW_TLB = 69
KVM_CAP_ONE_REG = 70
KVM_CAP_S390_GMAP = 71
KVM_CAP_TSC_DEADLINE_TIMER = 72
KVM_CAP_S390_UCONTROL = 73
KVM_CAP_SYNC_REGS = 74
KVM_CAP_PCI_2_3 = 75
KVM_CAP_KVMCLOCK_CTRL = 76
KVM_CAP_SIGNAL_MSI = 77
KVM_CAP_PPC_GET_SMMU_INFO = 78
KVM_CAP_S390_COW = 79
KVM_CAP_PPC_ALLOC_HTAB = 80
KVM_CAP_READONLY_MEM = 81
KVM_CAP_IRQFD_RESAMPLE = 82
KVM_CAP_PPC_BOOKE_WATCHDOG = 83
KVM_CAP_PPC_HTAB_FD = 84
KVM_CAP_S390_CSS_SUPPORT = 85
KVM_CAP_PPC_EPR = 86
KVM_CAP_ARM_PSCI = 87
KVM_CAP_ARM_SET_DEVICE_ADDR = 88
KVM_CAP_DEVICE_CTRL = 89
KVM_CAP_IRQ_MPIC = 90
KVM_CAP_PPC_RTAS = 91
KVM_CAP_IRQ_XICS = 92
KVM_CAP_ARM_EL1_32BIT = 93
KVM_CAP_SPAPR_MULTITCE = 94
KVM_CAP_EXT_EMUL_CPUID = 95
KVM_CAP_HYPERV_TIME = 96
KVM_CAP_IOAPIC_POLARITY_IGNORED = 97
KVM_CAP_ENABLE_CAP_VM = 98
KVM_CAP_S390_IRQCHIP = 99
KVM_CAP_IOEVENTFD_NO_LENGTH = 100
KVM_CAP_VM_ATTRIBUTES = 101
KVM_CAP_ARM_PSCI_0_2 = 102
KVM_CAP_PPC_FIXUP_HCALL = 103
KVM_CAP_PPC_ENABLE_HCALL = 104
KVM_CAP_CHECK_EXTENSION_VM = 105
KVM_CAP_S390_USER_SIGP = 106
KVM_CAP_S390_VECTOR_REGISTERS = 107
KVM_CAP_S390_MEM_OP = 108
KVM_CAP_S390_USER_STSI = 109
KVM_CAP_S390_SKEYS = 110
KVM_CAP_MIPS_FPU = 111
KVM_CAP_MIPS_MSA = 112
KVM_CAP_S390_INJECT_IRQ = 113
KVM_CAP_S390_IRQ_STATE = 114
KVM_CAP_PPC_HWRNG = 115
KVM_CAP_DISABLE_QUIRKS = 116
KVM_CAP_X86_SMM = 117
KVM_CAP_MULTI_ADDRESS_SPACE = 118
KVM_CAP_GUEST_DEBUG_HW_BPS = 119
KVM_CAP_GUEST_DEBUG_HW_WPS = 120
KVM_CAP_SPLIT_IRQCHIP = 121
KVM_CAP_IOEVENTFD_ANY_LENGTH = 122
KVM_CAP_HYPERV_SYNIC = 123
KVM_CAP_S390_RI = 124
KVM_CAP_SPAPR_TCE_64 = 125
KVM_CAP_ARM_PMU_V3 = 126
KVM_CAP_VCPU_ATTRIBUTES = 127
KVM_CAP_MAX_VCPU_ID = 128
KVM_CAP_X2APIC_API = 129
KVM_CAP_S390_USER_INSTR0 = 130
KVM_CAP_MSI_DEVID = 131
KVM_CAP_PPC_HTM = 132
KVM_CAP_SPAPR_RESIZE_HPT = 133
KVM_CAP_PPC_MMU_RADIX = 134
KVM_CAP_PPC_MMU_HASH_V3 = 135
KVM_CAP_IMMEDIATE_EXIT = 136
KVM_CAP_MIPS_VZ = 137
KVM_CAP_MIPS_TE = 138
KVM_CAP_MIPS_64BIT = 139
KVM_CAP_S390_GS = 140
KVM_CAP_S390_AIS = 141
KVM_CAP_SPAPR_TCE_VFIO = 142
KVM_CAP_X86_DISABLE_EXITS = 143
KVM_CAP_ARM_USER_IRQ = 144
KVM_CAP_S390_CMMA_MIGRATION = 145
KVM_CAP_PPC_FWNMI = 146
KVM_CAP_PPC_SMT_POSSIBLE = 147
KVM_CAP_HYPERV_SYNIC2 = 148
KVM_CAP_HYPERV_VP_INDEX = 149
KVM_CAP_S390_AIS_MIGRATION = 150
KVM_CAP_PPC_GET_CPU_CHAR = 151
KVM_CAP_S390_BPB = 152
KVM_CAP_GET_MSR_FEATURES = 153
KVM_CAP_HYPERV_EVENTFD = 154
KVM_CAP_HYPERV_TLBFLUSH = 155
KVM_CAP_S390_HPAGE_1M = 156
KVM_CAP_NESTED_STATE = 157
KVM_CAP_ARM_INJECT_SERROR_ESR = 158
KVM_CAP_MSR_PLATFORM_INFO = 159
KVM_CAP_PPC_NESTED_HV = 160
KVM_CAP_HYPERV_SEND_IPI = 161
KVM_CAP_COALESCED_PIO = 162
KVM_CAP_HYPERV_ENLIGHTENED_VMCS = 163
KVM_CAP_EXCEPTION_PAYLOAD = 164
KVM_CAP_ARM_VM_IPA_SIZE = 165
KVM_CAP_MANUAL_DIRTY_LOG_PROTECT = 166
KVM_CAP_HYPERV_CPUID = 167
KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 = 168
KVM_CAP_PPC_IRQ_XIVE = 169
KVM_CAP_ARM_SVE = 170
KVM_CAP_ARM_PTRAUTH_ADDRESS = 171
KVM_CAP_ARM_PTRAUTH_GENERIC = 172
KVM_CAP_PMU_EVENT_FILTER = 173
KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 = 174
KVM_CAP_HYPERV_DIRECT_TLBFLUSH = 175
KVM_CAP_PPC_GUEST_DEBUG_SSTEP = 176
KVM_CAP_ARM_NISV_TO_USER = 177
KVM_CAP_ARM_INJECT_EXT_DABT = 178
KVM_CAP_S390_VCPU_RESETS = 179
KVM_CAP_S390_PROTECTED = 180
KVM_CAP_PPC_SECURE_GUEST = 181
KVM_CAP_HALT_POLL = 182
KVM_CAP_ASYNC_PF_INT = 183
KVM_CAP_LAST_CPU = 184
KVM_CAP_SMALLER_MAXPHYADDR = 185
KVM_CAP_S390_DIAG318 = 186
KVM_CAP_STEAL_TIME = 187
KVM_CAP_X86_USER_SPACE_MSR = 188
KVM_CAP_X86_MSR_FILTER = 189
KVM_CAP_ENFORCE_PV_FEATURE_CPUID = 190
KVM_CAP_SYS_HYPERV_CPUID = 191
